
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <telephony/dongle.h>
#include "uevent.h"
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include "sunxi_ril.h"
#include "dongle_config.h"
#include "ppp_ctrl.h"
#include "modem_usb.h"
#include "atchannel.h"
#include "dongle_util.h"
#define LOG_TAG "DONGLE"
#include <utils/Log.h>

struct _DongleConfig {
	int 			matched_array[MAX_MATCHED_CANDIDATE];
	unsigned int	vid_pid;	
	int 			cur;
	int 			total;
	char*			name;		
};

static int dc_get_cur_modem_index(DongleConfig* thiz)
{
	return thiz->matched_array[thiz->cur];
}

struct modem_info* dc_get_current_modem_info(DongleConfig* thiz)
{
	if(thiz != NULL && thiz->cur < thiz->total && dc_get_cur_modem_index(thiz) != -1) 
	{
		return &modem_table[thiz->matched_array[thiz->cur]];
	}
		
	return NULL;
}

void dc_filt_dm_config(DongleConfig* thiz)
{
	int i = 0;
	int index = 0;
	struct modem_info* info;
	if(thiz != NULL)
	{
		for(; i < thiz->total; i++)	
		{	
			index = thiz->matched_array[i];
			info = &modem_table[index];
			if(check_is_dm_dongle_by_modem_info(info))
			{
				// set flag
				thiz->matched_array[i] = -1;
			}
		}

	}
}

int dc_get_config_length(DongleConfig* thiz)
{	
	if(thiz != NULL) 
	{
#ifdef DONGLE_LOG 
		ALOGD("%s: config length:%d", __func__, thiz->total);
#endif
		return thiz->total;
	}

	return 0;
}

void dc_destroy(DongleConfig* thiz)
{
	if(thiz != NULL)
	{
		if(thiz->name != NULL)
		{
			free(thiz->name);
			thiz->name == NULL;
		}
#ifdef DONGLE_LOG
		ALOGD("%s:%d", __func__, __LINE__);
#endif
		free(thiz);
		thiz == NULL;
	}
}

struct modem_info* dc_turn_next_info(DongleConfig* thiz)
{
	if(thiz != NULL && thiz->cur < thiz->total)
	{
		thiz->cur++;
		while(thiz->cur < thiz->total && dc_get_cur_modem_index(thiz) == -1) 
		{
			thiz->cur++;
		}
		if(thiz->cur == thiz->total)
		{
			thiz->cur = 0;
		}
		if(thiz->cur < thiz->total)
		{
#ifdef DONGLE_LOG
			ALOGD("%s cur index:%d", __func__, thiz->cur);
			modem_info_dump(&modem_table[dc_get_cur_modem_index(thiz)]);
#endif
			return &modem_table[dc_get_cur_modem_index(thiz)];
		}
	}

	return NULL;
}

int dc_name_specified(DongleConfig* thiz)
{
	return thiz != NULL && thiz->name != NULL;
}

DongleConfig* dc_create(const char* name, unsigned int vid_pid)
{
	DongleConfig* thiz = calloc(1, sizeof(DongleConfig));
	unsigned int i = 0;
    int ignore_name = (name == NULL);
    int count = 0;
	
	//TODO check parameter here
	thiz->vid_pid = vid_pid;
	if(!ignore_name)
	{
		thiz->name = strdup(name);
	}
	
#ifdef DONGLE_LOG
	ALOGD("Create candidate array with vid_pid:%08x,name:%s", vid_pid, name);
#endif
    	
	//Priority search in the internal table
	for(i = 0; i< MODEM_TABLE_SIZE; i++) 
	{	
#ifdef DONGLE_LOG
		//modem_info_dump(&modem_table[i]);
#endif
        if((vid_pid == modem_table[i].pid_vid_now))
        {	
        	if(ignore_name || !strcmp(name, modem_table[i].production_name)) 
        	{
            	thiz->matched_array[count++] = i;
            	if(count > MAX_MATCHED_CANDIDATE - 1) 
            	{
            		break;
            	}
        	}
        } 
    }
    thiz->total = count;

#ifdef DONGLE_LOG
   	ALOGD("find %d config for vid-pid:%08x,name:%s in int table", count, vid_pid, name);
#endif
	return thiz;
}

void dc_dump(DongleConfig* thiz)
{
#ifdef DONGLE_LOG
	if(thiz != NULL) 
	{
		int i = 0;
		struct modem_info* info = NULL;
		ALOGD("======================DongleConfig==========================");
		for(; i < thiz->total; i++) 
		{
			if(thiz->matched_array[i] != -1) 
			{
				info = &modem_table[thiz->matched_array[i]];
				modem_info_dump(info);
			}
		}
		ALOGD("==========================END===============================");
	}
#endif
}
